<template>
  <common-page
    class="add-data-set"
    :title="`${
      isEdit && isDrag
        ? '编辑数据集—' + dataSetTitle
        : isEdit && !isDrag
        ? '预览数据集—' + dataSetTitle
        : '新增数据集'
    }（所属分类：${typeName}）`"
  >
    <div slot="header-content" class="header-edit-name">
      <span class="line">|</span>
      <span class="label">数据集名称：</span>
      <span v-if="isEdit && !isDrag" class="header-edit header-name">{{
        form.name
      }}</span>
      <common-input
        v-else
        class="header-edit"
        v-model="form.name"
        placeholder="请输入数据集名称"
        :maxlength="16"
        clearable
      ></common-input>
    </div>
    <el-button slot="header" @click="$emit('close')">返回</el-button>
    <el-button
      slot="header"
      type="primary"
      @click="submitForm"
      v-if="isDrag"
      :loading="loading"
      >保存</el-button
    >

    <div
      class="add-data-set-main"
      slot="content"
      ref="addDataSetMain"
      v-loading="isPageDataLoading"
    >
      <!-- 左侧组件面板区域 -->
      <div class="component-list">
        <div class="component-list-label">组件面板</div>
        <div class="list">
          <div v-for="(item, index) in components">
            <span class="components_item_label">{{ item.label }}</span>
            <div
              v-for="(c, c_index) in item.children"
              :class="[
                'list-item',
                isDrag ? 'list-item-isDrag' : '',
                currentName === c.label && isDrag ? 'active' : '',
              ]"
              @mousedown="mousedown(c, c_index)"
              @mouseup="mouseup"
            >
              <div class="item-label">
                <svg class="svg-icon">
                  <use :xlink:href="'#' + c.icon"></use>
                </svg>
                <span>{{ c.label }}</span>
              </div>
              <i class="iconfont icon-point-btton"></i>
            </div>
          </div>
        </div>
      </div>

      <!--右侧流程拖拽区域-->
      <div class="js-plumb-container">
        <div
          class="item-container-scale"
          :style="{ width: viewWidth + 'px', height: viewHeight + 'px' }"
        >
          <div
            id="itemContainer"
            class="itemContainer"
            ref="itemContainer"
          ></div>
        </div>
        <div class="available-btn" @click="showVariable">
          <i class="iconfont icon-a-0_canshu_canshushezhi"></i>
          <span>变量</span>
        </div>
      </div>

      <!-- 右击菜单弹窗 -->
      <div
        class="contextmenu"
        v-show="contextmenuShow"
        :style="{ top: contextmenuTop + 'px', left: contextmenuLeft + 'px' }"
      >
        <div v-if="contextmenuType">
          <!--          <div class="contextmenu-button" @click="handleCopy"><span>复制节点</span><span>Ctrl + C</span></div>-->
          <div class="contextmenu-button" @click="deleteFlow">
            <span>删除节点</span><span>Delete</span>
          </div>
        </div>
        <div v-else>
          <!--          <div class="contextmenu-button" @click="handlePaste"><span>粘贴节点</span><span>Ctrl + V</span></div>-->
        </div>
      </div>
    </div>

    <!-- 组件配置项弹窗 -->
    <el-drawer
      slot="content"
      :title="title"
      :visible.sync="dialogShow"
      direction="rtl"
      :modal-append-to-body="true"
      append-to-body
      size="580px"
      :before-close="handleCloseComponents"
      ref="componentDialog"
    >
      <component
        ref="componentItem"
        :is="componentType"
        :option="nodeOption"
        :variable="getAllVariableData"
        :variableConfig="getAllVariableConfig"
        :isDisabled="!isDrag"
        :nodeDataTemp="nodeDataTemp"
        @changeForm="changeForm"
      ></component>
      <!--      <keep-alive>-->
      <!--        <component-->
      <!--          ref="componentItem"-->
      <!--          :is="componentType"-->
      <!--          @changeForm="changeForm"-->
      <!--          :option="nodeOption"-->
      <!--          :dataSourceList="dataSourceList"-->
      <!--          :variable="getAllVariableData"-->
      <!--        ></component>-->
      <!--      </keep-alive>-->
    </el-drawer>

    <!-- 变量配置弹窗 -->
    <el-drawer
      title="变量配置"
      :visible.sync="variableDialogShow"
      append-to-body
      direction="rtl"
      :modal-append-to-body="false"
      size="580px"
      :before-close="handleClose"
      ref="variableDialog"
    >
      <VariableConfig
        ref="variableConfig"
        :variableConfig="variableConfig"
        :globalList="globalList"
        :isDisabled="!isDrag"
        :nodeData="nodeData"
        @changeVariableConfig="changeVariableConfig"
      ></VariableConfig>
    </el-drawer>

    <!-- 保存弹窗 -->
    <common-edit-dialog
      title="保存"
      :visible="preservationShow"
      @cancel="cancel"
      @submit="submitForm"
      :button-loading="loading"
    >
      <el-form label-width="90px" :rules="rules" ref="form" :model="form">
        <el-form-item label="数据集名称" prop="name">
          <common-input clearable :maxlength="16" v-model="form.name" />
        </el-form-item>
        <common-add-dept
          ref="commonAddDept"
          :deptListParams="departmentList"
          @getCheckedDeptId="getCheckedDeptId"
          :deptId="form.deptId"
        ></common-add-dept>
        <el-form-item label="描述" prop="remark">
          <common-input
            type="textarea"
            :autosize="{ minRows: 4, maxRows: 8 }"
            v-model="form.remark"
            placeholder="请输入"
          />
        </el-form-item>
      </el-form>
    </common-edit-dialog>
  </common-page>
</template>

<script>
import {
  addDataSet,
  getDataSourceList,
  getInfo,
  editDataSet,
  checkSql,
  querySourceList,
} from "@/api/screenConfig/dataSet";
import { componentData } from "./flowData";
import MysqlTableInput from "./components/MysqlTableInput";
import FieldConfig from "./components/FieldConfig";
import FieldConfig2 from "./components/FieldConfig2";
import ESTableInput from "./components/ESTableInput";
import APIInput from "./components/APIInput";
import RowToCellConfig from "./components/RowToCellConfig";
import VariableConfig from "./components/VariableConfig";
import ProcessConfig from "./mixin/processConfig";
import { globalList } from "@/api/screenConfig/global";
import { _deepClone } from "@/utils";

export default {
  name: "add",
  components: {
    MysqlTableInput,
    FieldConfig,
    // FieldConfig2,
    ESTableInput,
    VariableConfig,
    APIInput,
    RowToCellConfig,
  },
  mixins: [ProcessConfig],
  props: {
    departmentList: {
      type: Array,
      default: () => [],
    },
    // dataSourceList: {
    //   type: Array,
    //   default: () => []
    // },
    globalList: {
      type: Array,
      default: () => [],
    },
    typeId: {
      type: [Number, String],
    }, //分类id
    typeName: {
      type: String,
      default: "无",
    }, //分类名称
    // formData: {
    //   type: String,
    //   default: null
    // }
  },
  data() {
    return {
      isPageDataLoading: false,
      dataSetTitle: "", //数据集名称
      formData: null,
      form: {
        id: null,
        name: "",
        remark: "",
        deptId: null,
      },
      rules: {
        name: [
          {
            required: true,
            message: "请输入数据集名称",
            trigger: "blur",
          },
        ],
        // deptId: [{ required: true, message: '请选择组织', trigger: 'blur' }],
      },
      dataSource: [
        {
          type: "MysqlTableInput",
          datasourceType: "MYSQL",
        },
        {
          type: "ESTableInput",
          datasourceType: "ES",
        },
      ],
      preservationShow: false, //保存弹窗
      isEdit: false,
      loading: false,
      dialogShow: false, //组件弹窗开关
      title: "", //弹窗标题
      components: componentData, //组件集
      componentType: null, //组件类型
      currentName: null,
      moveFlowDom: null, //组件拖拽时创建的dom元素
      viewWidth: "0",
      viewHeight: "0",
      itemContainer: null, //流程区域dom元素
      jsPlumbObj: null,
      nodeData: [], //所有节点数据集
      lineData: [], //所有连接线数据集
      contextmenuShow: false, //右击菜单弹窗
      contextmenuTop: 0, //右击菜单弹窗位置
      contextmenuLeft: 0, //右击菜单弹窗位置
      contextmenuType: false, //右击菜单类型
      selectFlowData: null, //选中的节点数据
      targetEndpoint: null, //目标节点数据
      nodeOption: null,
      tempNodeOptionData: null, //打开弹窗时暂存节点数据，用于对比关闭弹窗时数据是否一致
      variableDialogShow: false, //变量配置弹窗
      variableConfig: [], //局部变量配置
      isDrag: true, //是否可操作，预览流程时为false，禁止操作
      variableIds: "", // sql输入节点中sql用到的变量id集合
      nodeDataTemp: [], //当前节点前面所有节点集合
    };
  },
  watch: {
    dialogShow(val) {
      this.selectFlowData.select = val;
      this.changeFlowDom(this.selectFlowData);
      if (!val && this.selectFlowData.option) {
        this.selectFlowData.name = this.selectFlowData.option.name
          ? this.selectFlowData.option.name
          : "";
        //修改流程节点name
        this.setFlowDataName(this.selectFlowData);
        //判断当前节点是否改变，修改关联节点的complete状态
        this.changeFlowDataComplete();
      }
      if (val) {
        this.nodeDataTemp = this.getNodeDataTemp(this.selectFlowData.lastId);
      }
    },
  },
  computed: {
    getAllVariableData() {
      return [...this.variableConfig, ...this.globalList].reduce((r, c) => {
        if (!r.find((f) => f.label === c.name)) {
          r.push({
            label: c.name,
            value: c.name,
          });
        }
        return r;
      }, []);
    },
    getAllVariableConfig() {
      return [...this.variableConfig, ...this.globalList];
    },
  },
  methods: {
    getCheckedDeptId(val) {
      this.form.deptId = val;
    },
    /**
     * 打开节点配置弹窗
     */
    showOption() {
      this.dialogShow = true;
    },
    /**
     * 关闭保存弹窗
     */
    cancel() {
      this.preservationShow = false;
    },
    /**
     * 保存按钮
     */
    submit() {
      this.preservationShow = true;
    },
    /**
     * 新增/编辑接口
     * @params params
     */
    submitConfigData(params) {
      return new Promise((resolve, reject) => {
        if (params.id) {
          editDataSet(params).then((res) => {
            resolve(res);
          });
        } else {
          addDataSet(params).then((res) => {
            resolve(res);
          });
        }
      });
    },
    /**
     * 点击节点打开配置项
     * @param config
     */
    setOption(config) {
      //判断输出节点是否已连接
      if (config.componentType === "OutInput" && !config.isConnect) {
        return this.$message({
          type: "warning",
          message: "该节点需先配置前置节点，才能打开配置项!",
        });
      }
      // console.log(config.option)
      this.title = config.label;
      this.componentType = config.type;
      this.nodeOption = config.option;
      this.dialogShow = true;
      //弹窗打开时临时存储配置项数据，用于和关闭弹窗时做对比
      this.tempNodeOptionData = JSON.stringify(config.option);

      if (config.isConnect) {
        this.$nextTick(() => {
          let lineData = this.getAllConnectLineData().find(
            (f) => f.right === config.id
          );
          if (lineData) {
            let sourceNode = this.nodeData.find((f) => f.id === lineData.left);
            this.$refs.componentItem.initData(sourceNode);
          }
        });
      }
    },
    /**
     * 获取组件弹窗中配置项
     * @param option  选中节点配置项
     * @param complete 选中节点状态
     * @param isUpdate  是否需要修改配置项数据
     */
    changeForm(option, complete, isUpdate) {
      this.selectFlowData.option = _deepClone(option);
      this.selectFlowData.complete = complete;
      if (isUpdate) {
        this.changeNodeData();
      }
    },
    /**
     * 修改节点配置项数据
     */
    changeNodeData() {
      let nodeData = this.nodeData.find((f) => f.id === this.selectFlowData.id);
      if (nodeData) {
        nodeData.option = this.selectFlowData.option;
        nodeData.complete = this.selectFlowData.complete;
      }
    },
    /**
     * 设置配置名称
     */
    setFlowDataName(selectFlowData) {
      let dom = document
        .querySelectorAll(`[data-id="${selectFlowData.id}"]`)[0]
        .getElementsByTagName("span")[0];
      dom.innerText = this.selectFlowData.option.name;
    },
    /**
     * 打开变量配置弹窗
     */
    showVariable() {
      this.variableDialogShow = true;
      this.$nextTick(() => {
        this.$refs.variableConfig.init();
      });
    },
    /**
     * 变量配置组件回传数据
     */
    changeVariableConfig(data) {
      this.variableConfig = data;
    },
    /**
     * 修改相邻节点的complete状态
     */
    changeFlowDataComplete() {
      //判断是否可操作
      if (!this.isDrag) return;

      if (
        this.tempNodeOptionData !== JSON.stringify(this.selectFlowData.option)
      ) {
        let lineData = this.getAllConnectLineData();
        if (!lineData.length) return;
        let lineItem = lineData.find((f) => f.left === this.selectFlowData.id);
        let targetData = lineItem
          ? this.nodeData.find((item) => item.id === lineItem.right)
          : null;
        if (targetData) {
          targetData.complete = false;
          this.$message({
            type: "warning",
            message: "数据发生变化，请重新配置字段配置节点!",
          });
        }
      }
    },
    /**
     * 组件配置弹窗关闭前事件处理
     */
    handleCloseComponents(done) {
      //是否是预览状态
      if (!this.isDrag) {
        done();
        return;
      }
      //调用组件自定义校验方法
      //组件内统一校验方法名：checkFormBeforeClose
      let result = this.$refs.componentItem.checkFormBeforeClose
        ? this.$refs.componentItem.checkFormBeforeClose()
        : null;
      if (
        !this.$refs.componentItem.checkFormBeforeClose ||
        (result && result === "ok")
      ) {
        this.changeNodeData();
        done();
      }
    },
    /**
     * 关闭变量弹窗前处理数据
     */
    handleClose(done) {
      let variableDialogRef = this.$refs.variableDialog;
      if (variableDialogRef && variableDialogRef.$children?.length) {
        let result = variableDialogRef.$children[0].checkFormBeforeClose();
        if (result && result === "ok") {
          done();
        }
      } else {
        done();
      }
    },
    /**
     * 右击显示菜单
     * @param event
     */
    showContextmenu(event) {
      if (!this.isDrag) return;
      this.contextmenuShow = true;
      let { pageX, pageY } = event,
        { top, left } = this.$refs.addDataSetMain.getBoundingClientRect();
      // 右击菜单显示位置
      this.contextmenuTop = pageY - top;
      this.contextmenuLeft = pageX - left;
    },

    /**
     * 保存前检查各节点配置项是否配置完成
     */
    checkConfigDataStatus() {
      if (
        this.nodeData.length &&
        !this.nodeData.find((item) => item.componentType === "Input")
      ) {
        return false;
      } else if (this.nodeData.length === 1) {
        return this.nodeData.every((item) => item.complete);
      } else {
        return (
          this.nodeData.length && this.nodeData.every((item) => item.complete)
        );
      }
    },
    /**
     * 获取节点为sql输入时sql中使用到的全局变量id集合
     * @returns {string|string}
     */
    getVariableIds() {
      let flowData = this.nodeData.find(
        (item) => item.type === "MysqlTableInput"
      );
      if (flowData && flowData.option.sql) {
        let sql = flowData.option.sql;
        let regex = new RegExp("\\{(.+?)\\}", "g");
        let variableList =
          sql.match(regex) &&
          sql.match(regex).map((f) => f.replace(new RegExp("\\{|}", "g"), ""));
        return variableList && variableList.length
          ? variableList
              .reduce((r, c) => {
                if (this.getAllVariableConfig.find((f) => f.name === c)) {
                  r.push(
                    this.getAllVariableConfig.find((f) => f.name === c).id
                  );
                }
                return r;
              }, [])
              .join(",")
          : "";
      }
      return "";
    },
    /**
     * 保存数据
     */
    submitForm() {
      if (!this.form.name)
        return this.$GlobalErrorConfirm(
          this.isEdit ? "编辑失败" : "新增失败",
          "请输入数据集名称"
        );
      let flowConfig = JSON.stringify({
        line: this.getAllConnectLineData(),
        node: this.nodeData,
      });

      let nodeData = this.nodeData.find((f) => f.componentType === "Input");
      let datasourceType =
        nodeData && nodeData.type === "APIInput"
          ? "API"
          : nodeData && nodeData.type !== "APIInput"
          ? this.dataSource.find((f) => f.type === nodeData.type).datasourceType
          : "";
      let params = {
        type: this.typeId,
        ...this.form,
        flowConfig,
        datasource:
          nodeData && nodeData.type !== "APIInput"
            ? nodeData.option.dataSourceId
            : "",
        variableConfig: JSON.stringify(this.variableConfig),
        datasourceType: datasourceType,
        nodeNum: this.nodeData.length,
        globalVariableId: this.getVariableIds(),
        status: this.checkConfigDataStatus() ? 0 : 1,
        classType: 1,
      };
      this.loading = true;
      this.submitConfigData(params)
        .then((res) => {
          if (res && res.code === 200) {
            this.$GlobalSuccessMessage(this.isEdit ? "编辑成功" : "新增成功");
            this.cancel();
            this.$emit("close");
            this.$emit("refresh");
          } else {
            this.$GlobalErrorConfirm(
              this.isEdit ? "编辑失败" : "新增失败",
              res.msg
            );
          }
        })
        .finally(() => {
          this.loading = false;
          this.preservationShow = false;
        });
    },

    /**
     * 获取当前节点的之前所有节点数据
     *
     */
    getNodeDataTemp(lastId, nodeData) {
      let result = nodeData ? nodeData : [];
      this.nodeData.forEach((item) => {
        if (item.id === lastId) {
          result.push(item);
          if (item.lastId) this.getNodeDataTemp(item.lastId, result);
        }
      });
      return result;
    },
    // ---------------------- 数据初始化 ---------------------

    /**
     * 处理初始化节点数据
     */
    // handleNodeData() {
    //   if()
    // },
    /**
     * 根据id获取数据
     */
    initData(info, isTrue) {
      if (info?.id) {
        this.isEdit = true;
        this.isDrag = isTrue;
        this.dataSetTitle = info?.name || "";
        this.isPageDataLoading = true;
        getInfo({ id: info.id })
          .then((res) => {
            if (res && res.code === 200) {
              Reflect.ownKeys(this.form).forEach(
                (k) => (this.form[k] = res.data[k])
              );
              this.formData = res.data.flowConfig;
              try {
                this.variableConfig = res.data.variableConfig
                  ? JSON.parse(res.data.variableConfig).filter(
                      (f) => f.variableType === "局部"
                    )
                  : [];
                let { line, node } = JSON.parse(this.formData);
                this.nodeData = node;
                this.nodeData.forEach((n) => {
                  //兼容旧数据方法
                  if (!n.lastId && !n.nextId) {
                    n.nextId = line.find((l) => l.left === n.id)?.right || "";
                    n.lastId = line.find((l) => l.right === n.id)?.left || "";
                  }
                  //创建节点
                  this.addFlowItem({ ...n });
                });
                line.forEach((l) => {
                  let sourceInfo = `${l.left}_Right`;
                  let targetInfo = `${l.right}_Left`;
                  //创建连线
                  this.addLine([sourceInfo, targetInfo]);
                });

                // this.globalVariableArray = variable ? variable : []
              } catch (e) {
                console.error("JSON转换异常: ", e);
              }
            } else {
              this.$GlobalErrorConfirm(
                "获取数据失败",
                res.msg,
                "重新加载"
              ).then(() => {
                this.initData(info.id);
              });
            }
          })
          .finally((err) => {
            this.isPageDataLoading = false;
          });
      }
    },
  },
};
</script>

<style scoped lang="scss">
.add-data-set {
  .add-data-set-main {
    font-size: 14px;
    width: 100%;
    height: 100%;
    color: #303133;
    display: flex;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    position: relative;

    .component-list {
      padding-right: 12px;
      width: 200px;
      border-right: 1px solid #eee;
      height: 100%;
      box-sizing: border-box;

      .component-list-label {
        font-size: 16px;
        font-weight: bold;
        padding-left: 12px;
        padding-top: 12px;
      }

      .list {
        margin-top: 12px;

        .components_item_label {
          color: #666666;
          padding-left: 12px;
          margin: 4px 0;
          display: flex;
        }

        .list-item {
          padding: 6px 6px 6px 24px;
          align-items: center;
          display: flex;
          justify-content: space-between;

          .item-label {
            display: flex;
            align-items: center;

            .svg-icon {
              width: 14px;
              height: 14px;
              margin-right: 8px;
            }
          }

          .icon-point-btton {
            font-size: 14px;
            opacity: 0;
          }
        }

        .list-item-isDrag {
          cursor: pointer;

          &:hover {
            background-color: var(--theme-color-opacity);

            .icon-point-btton {
              opacity: 1;
            }

            /*color: #72bbff;*/
          }
        }

        .active {
          color: var(--theme-color);
          background-color: var(--theme-color-opacity);
        }
      }
    }

    .js-plumb-container {
      flex: 1;
      overflow: auto;
      position: relative;
      background-image: url("../../../../assets/images/grid.png");
      background-size: 100px 100px;
      background-repeat: repeat;

      .item-container-scale {
        .itemContainer {
          width: 100%;
          height: 100%;
          position: relative;

          ::v-deep .jtk-endpoint {
            z-index: 99;
          }
        }
      }

      .available-btn {
        position: absolute;
        top: 32px;
        left: 32px;
        color: var(--theme-color);
        cursor: pointer;
        display: flex;
        align-items: center;

        .icon-a-0_canshu_canshushezhi {
          margin-right: 4px;
        }
      }
    }

    .contextmenu {
      position: absolute;
      padding: 4px 0;
      width: 156px;
      background-color: #ffffff;
      z-index: 1199;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
      border-radius: 2px;
      border: 1px solid #ebeef5;

      .contextmenu-button {
        height: 32px;
        line-height: 32px;
        padding-left: 16px;
        cursor: pointer;

        span:first-child {
          margin-right: 36px;
          display: inline-block;
          font-size: 12px;
          color: #606266;
        }

        span:nth-child(2) {
          color: #909399;
        }

        &:hover {
          background-color: #f5f7fa;
        }
      }

      .divide {
        margin: 4px 0;
        width: 156px;
        height: 1px;
        background-color: #e4e7ed;
      }
    }
  }

  ::v-deep .el-drawer__header {
    font-weight: bold;
    margin-bottom: 20px;
    color: #303133;
  }
}
.header-edit-name {
  display: flex;
  align-items: center;

  .line {
    color: #303133;
    margin-right: 18px;
  }

  .label {
    width: 90px;
    color: #303133;
    font-size: 14px;
    box-sizing: border-box;
  }

  .header-edit {
    width: calc(100% - 112px);
  }

  .header-name {
    font-size: 14px;
    color: #303133;
  }
}
</style>
